package GUI;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;

import MediaLibrary.MediaLibrary;
import Streaming.HTTPServer;
import Streaming.StreamingModule;

public class MainUI implements ActionListener{
	private JFrame frame;
	private JPanel libPan;
	private JPanel userPan;
	private JPanel infoPan;
	private JPanel controlPan;
	
	// vars for Library view
	private MediaLibrary medLib;
	private JList<String> libraryList;
	private DefaultListModel<String> libraryListModel;
	
	// vars for Playing view
	private String curInfo = "Not Playing";
	private JLabel label;
	
	// vars for Control view
	private JButton play = new JButton("Play");
	private JButton stop = new JButton("Stop");
	private JButton next = new JButton("Next");
	
	// vars for User view
	private Vector<String> connectedUsers;
	private JList<String> userList;
	private DefaultListModel<String> userListModel;
	private int index;
	
	// multithread and networking stuff
	private HTTPServer httpServer;
	private StreamingModule streamer;
	private final ExecutorService pool;
	private Thread streamThread;
	
	
	public static void run() {
		
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					new MainUI();
				}
			});
	}	
	
	private MainUI(){
		frame = new JFrame("It was Pain! Server");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Container contentPane = frame.getContentPane();
		contentPane.setLayout(new BorderLayout());
		
		//Menu(Menu/Exit, Menu/Add Folder, User Manager)
		JMenuBar bar = new JMenuBar();
		JMenu fileMenu = new JMenu("File");
		
		JMenuItem exit = new JMenuItem("Exit");
		exit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				frame.dispose();
			}
		});
		
		JMenuItem addFolder = new JMenuItem("Add Music Folder");
		addFolder.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				addContent();
				frame.pack();
				
				
			}
		});	
		
		JMenuItem deleteLib = new JMenuItem("Delete Musik Library");
		deleteLib.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				clearList();
				frame.pack();
				
			}
		});
		
		JMenu userMenu = new JMenu("User");
		JMenuItem kick = new JMenuItem("Kick");
		kick.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(!connectedUsers.isEmpty()){
					String kickuser = connectedUsers.get(userList.getSelectedIndex());
					connectedUsers.remove(kickuser);
					
					updateUserList();
					frame.pack();
				}
			}
		});
		
		play.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {				

				index = (libraryList.getSelectedIndex() < 0) ? 1 : index;
				
				label.setText(medLib.getFiles().get(index).getName());
				label.updateUI();
				
				streamer = new StreamingModule(medLib.getFiles(), connectedUsers, index);
				streamer.addListener(this);
//				streamThread = new Thread(streamer);
//				pool.execute(streamThread);	
				streamer.transmit();
			}
		});
		
		stop.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				streamer.stopPlaying();		
//				try {
//					streamThread.join();
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
			}
		});
		
		next.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				index = (++index > medLib.getFiles().size()) ? 0 : index;
				
				streamer = new StreamingModule(medLib.getFiles(), connectedUsers, index);
//				streamThread = new Thread(streamer);
//				pool.execute(streamThread);
				streamer.transmit();
			}
		});

		
		fileMenu.add(addFolder);
		fileMenu.add(deleteLib);
		fileMenu.add(exit);
		userMenu.add(kick);
		bar.add(fileMenu);
		bar.add(userMenu);
		frame.setJMenuBar(bar);
		
		libPan = initLibPanel();
		infoPan = initInfoPanel();
		userPan = initUserPanel();
		controlPan = initControlPanel();
		
		
		contentPane.add(libPan, BorderLayout.CENTER);
		contentPane.add(infoPan, BorderLayout.NORTH);
		contentPane.add(userPan, BorderLayout.WEST);
		contentPane.add(controlPan, BorderLayout.SOUTH);
		frame.setVisible(true);
		frame.pack();
		
		// non UI elements
		this.medLib = new MediaLibrary();
		
		httpServer = new HTTPServer();
		httpServer.addListener(this);
		pool = Executors.newFixedThreadPool(2);
		pool.execute(httpServer);
		
		addLibContent();
	}

	
	@Override
	public void actionPerformed(ActionEvent e) {
		curInfo = e.getActionCommand();
		
		if(curInfo.startsWith("New user connected")){
			updateUserList();
		}
		else if(curInfo.startsWith("Streaming module")){
			label.setText(curInfo);
			label.updateUI();
			infoPan.updateUI();
		}
	}

	private JPanel initControlPanel() {
		JPanel panel = new JPanel();
		panel.setBorder(BorderFactory.createTitledBorder("Controls"));
		panel.setLayout(new GridLayout(0, 3));
		panel.add(play);
		panel.add(stop);
		panel.add(next);
		return panel;
	}


	private JPanel initUserPanel() {
		JPanel panel = new JPanel();
		httpServer = new HTTPServer();
		connectedUsers = httpServer.getConnectedUsers();
		userListModel = new DefaultListModel<String>();
		if(connectedUsers.isEmpty())
			userListModel.addElement("No Users Connected!!");
		else{
			for (String s : connectedUsers) {
				userListModel.addElement(s);
			}
		}
		userList = new JList<String>(userListModel);
		userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		panel.setBorder(BorderFactory.createTitledBorder("Users Connected:"));
		panel.add(new JScrollPane(userList), BorderLayout.CENTER);
		return panel;
	}


	private JPanel initInfoPanel() {
		JPanel panel = new JPanel();
		label = new JLabel(curInfo);
		panel.setBorder(BorderFactory.createTitledBorder("Music Title:"));
		panel.add(label);
		panel.setAutoscrolls(true);
		return panel;
	}


	private JPanel initLibPanel() {
		JPanel panel = new JPanel();		

		libraryListModel = new DefaultListModel<String>();
		
		libraryListModel.addElement("Add some musik!!");
		
		libraryList = new JList<String>(libraryListModel);
		
		libraryList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		panel.add(new JScrollPane(libraryList));
		panel.setBorder(BorderFactory.createTitledBorder("Music Library"));
		
		return panel;
	}
	
	public void addLibContent() {
		if(libraryListModel.firstElement().equals("Add some musik!!"))libraryListModel.clear();
		
		ArrayList<String> media = medLib.openFile();
		libraryListModel.clear();
		if (media != null && media.size() != 0) {
			for (String title : media) {
				libraryListModel.addElement(title);
			}
		}
		libPan.repaint();
	}
	
	public void clearLib(){
		medLib.clearList();
		libraryListModel.clear();
		
		if(libraryListModel.isEmpty())
			libraryListModel.addElement("Add some musik!!");
		
		libPan.repaint();
	}
	
	private void addContent() {
		if(libraryListModel.firstElement().equals("Add some musik!!"))
			libraryListModel.clear();
		
		ArrayList<String> media = medLib.openFile();
		libraryListModel.clear();
		if (media != null) {
			for (String title : media) {
				libraryListModel.addElement(title);
			}
		}
		libPan.repaint();
	}
	
	private void clearList(){
		medLib.clearList();
		libraryListModel.clear();
		
		if(libraryListModel.isEmpty())
			libraryListModel.addElement("Add some musik!!");
		
		libPan.repaint();
	}
	
	private void updateUserList(){
		connectedUsers = httpServer.getConnectedUsers();
		for (String s : connectedUsers) {
			userListModel.addElement(s);
		}
		userPan.repaint();
	}
	
}
